home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / winsock / ircii2-6.zip / SRC\IRCII-2.6\SOURCE\DCC.C < prev    next >
C/C++ Source or Header  |  1995-01-04  |  39KB  |  1,648 lines

  1. /*
  2.  * dcc.c: Things dealing client to client connections. 
  3.  *
  4.  * Written By Troy Rollo <troy@cbme.unsw.oz.au> 
  5.  *
  6.  * Copyright(c) 1991 
  7.  *
  8.  * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
  9.  */
  10.  
  11. #ifndef lint
  12. static    char    rcsid[] = "@(#)$Id: dcc.c,v 1.41 1994/10/09 06:39:35 mrg Stab $";
  13. #endif
  14.  
  15. #include "irc.h"
  16.  
  17. #ifdef ESIX
  18. # include <lan/net_types.h>
  19. #endif /* ESIX */
  20.  
  21. #if defined(ISC30) && defined(_POSIX_SOURCE)
  22. # undef _POSIX_SOURCE
  23. #include <sys/stat.h>
  24. # define _POSIX_SOURCE
  25. #else
  26. # include <sys/stat.h>
  27. #endif /* ICS30 || _POSIX_SOURCE */
  28.  
  29. #include "talkd.h"
  30. #include "server.h"
  31. #include "ircaux.h"
  32. #include "whois.h"
  33. #include "lastlog.h"
  34. #include "ctcp.h"
  35. #include "dcc.h"
  36. #include "hook.h"
  37. #include "vars.h"
  38. #include "window.h"
  39. #include "output.h"
  40.  
  41. #ifndef O_BINARY
  42. #define O_BINARY 0
  43. #endif
  44. #ifndef _Windows
  45. #define    closesocket(x) close(x)
  46. #endif
  47.  
  48. extern    void    dcc_chat();
  49. extern    void    dcc_filesend();
  50. extern    void    dcc_getfile();
  51. extern    void    dcc_close();
  52. extern    void    dcc_talk();
  53. extern    void    dcc_tmsg();
  54. extern    void    dcc_rename();
  55. extern    void    dcc_summon();
  56. extern    void    dcc_send_raw();
  57. extern    void    process_incoming_chat();
  58. extern    void    process_outgoing_file();
  59. extern    void    process_incoming_file();
  60. extern    void    process_incoming_talk();
  61. extern    void    process_incoming_raw();
  62. extern    void    process_incoming_listen();
  63.  
  64. struct
  65. {
  66.     char    *name;
  67.     void    (*function)();
  68. }    dcc_commands[] =
  69. {
  70.     { "CHAT",    dcc_chat },
  71.     { "LIST",    dcc_list },
  72.     { "SEND",    dcc_filesend },
  73.     { "GET",    dcc_getfile },
  74.     { "CLOSE",    dcc_close },
  75.     { "TALK",    dcc_talk },
  76.     { "TMSG",    dcc_tmsg },
  77.     { "RENAME",    dcc_rename },
  78.     { "SUMMON",    dcc_summon },
  79.     { "RAW",    dcc_send_raw },
  80.     { NULL,        (void (*)()) NULL }
  81. };
  82.  
  83.     char    *dcc_types[] =
  84. {
  85.     "<null>",
  86.     "CHAT",
  87.     "SEND",
  88.     "GET",
  89.     "TALK",
  90.     "SUMMON",
  91.     "RAW_LISTEN",
  92.     "RAW",
  93.     NULL
  94. };
  95.  
  96. /* this is such a fucking kludge */
  97.  
  98. struct    deadlist
  99. {
  100.     DCC_list *it;
  101.     struct deadlist *next;
  102. }    *deadlist = NULL;
  103.  
  104. extern    int    in_ctcp_flag;
  105. extern    char    FAR MyHostName[];
  106. extern    struct    in_addr    MyHostAddr;
  107. static    off_t    filesize = 0;
  108.  
  109. DCC_list    *ClientList = NULL;
  110.  
  111. /*
  112.  * dcc_searchlist searches through the dcc_list and finds the client
  113.  * with the the flag described in type set.
  114.  */
  115. DCC_list *
  116. dcc_searchlist(name, user, type, flag, othername)
  117.     char    *name,
  118.         *user;
  119.     int    type,
  120.         flag;
  121.     char    *othername;
  122. {
  123.     DCC_list **Client, *NewClient;
  124.  
  125.     for (Client = (&ClientList); *Client ; Client = (&(**Client).next))
  126.     {
  127.         if ((((**Client).flags&DCC_TYPES) == type) &&
  128.             ((!name || (!my_stricmp(name, (**Client).description))) ||
  129.             (othername && (!my_stricmp(othername, (**Client).othername)))) &&
  130.             (my_stricmp(user, (**Client).user)==0))
  131.             return *Client;
  132.     }
  133.     if (!flag)
  134.         return NULL;
  135.     *Client = NewClient = (DCC_list *) new_malloc(sizeof(DCC_list));
  136.     NewClient->flags = type;
  137.     NewClient->read = NewClient->write = NewClient->file = -1;
  138.     NewClient->filesize = filesize;
  139.     NewClient->next = (DCC_list *) 0;
  140.     NewClient->user = NewClient->description = NewClient->othername = NULL;
  141.     NewClient->bytes_read = NewClient->bytes_sent = 0L;
  142.     NewClient->starttime = 0;
  143.     malloc_strcpy(&NewClient->description, name);
  144.     malloc_strcpy(&NewClient->user, user);
  145.     malloc_strcpy(&NewClient->othername, othername);
  146.     time(&NewClient->lasttime);
  147.     return NewClient;
  148. }
  149.  
  150. static    void
  151. dcc_add_deadclient(client)
  152.     DCC_list *client;
  153. {
  154.     struct deadlist *new;
  155.  
  156.     new = (struct deadlist *) new_malloc(sizeof(struct deadlist));
  157.     new->next = deadlist;
  158.     new->it = client;
  159.     deadlist = new;
  160. }
  161.  
  162. /*
  163.  * dcc_erase searches for the given entry in the dcc_list and
  164.  * removes it
  165.  */
  166. void
  167. dcc_erase(Element)
  168.     DCC_list    *Element;
  169. {
  170.     DCC_list    **Client;
  171.  
  172.     for (Client = &ClientList; *Client; Client = &(**Client).next)
  173.         if (*Client == Element)
  174.         {
  175.             *Client = Element->next;
  176.             closesocket(Element->write);
  177.             closesocket(Element->read);
  178.             if (Element->file != -1)
  179.                 close(Element->file);
  180.             new_free(&Element->description);
  181.             new_free(&Element->user);
  182.             new_free(&Element);
  183.             return;
  184.         }
  185. }
  186.  
  187. void
  188. dcc_really_erase()
  189. {
  190.     struct deadlist *dies;
  191.  
  192.     for (;(dies = deadlist) != NULL;)
  193.     {
  194.         deadlist = deadlist->next;
  195.         dcc_erase(dies->it);
  196.     }
  197. }
  198.  
  199. /*
  200.  * Set the descriptor set to show all fds in Client connections to
  201.  * be checked for data.
  202.  */
  203. void
  204. set_dcc_bits(rd, wd)
  205.     fd_set    *rd, *wd;
  206. {
  207.     DCC_list    *Client;
  208.  
  209.     for (Client = ClientList; Client != NULL; Client = Client->next)
  210.     {
  211.         if (Client->read != -1)
  212.             FD_SET(Client->read, rd);
  213.     }
  214. }
  215.  
  216. /*
  217.  * Check all DCCs for data, and if they have any, perform whatever
  218.  * actions are required.
  219.  */
  220. void
  221. dcc_check(Readables)
  222.     fd_set    *Readables;
  223. {
  224.     DCC_list    **Client;
  225.     struct    timeval    timeout;
  226.     int    previous_server;
  227.     int    lastlog_level;
  228.  
  229.     previous_server = from_server;
  230.     from_server = (-1);
  231.     timeout.tv_sec = timeout.tv_usec = 0;
  232.     message_from((char *) 0, LOG_DCC);
  233.     lastlog_level = set_lastlog_msg_level(LOG_DCC);
  234.     for (Client = (&ClientList); *Client != NULL && !break_io_processing;)
  235.     {
  236.         if ((*Client)->read != -1 && FD_ISSET((*Client)->read,
  237.                 Readables))
  238.         {
  239.             switch((*Client)->flags&DCC_TYPES)
  240.             {
  241.             case DCC_CHAT:
  242.                 process_incoming_chat(*Client);
  243.                 break;
  244.             case DCC_RAW_LISTEN:
  245.                 process_incoming_listen(*Client);
  246.                 break;
  247.             case DCC_RAW:
  248.                 process_incoming_raw(*Client);
  249.                 break;
  250.             case DCC_FILEOFFER:
  251.                 process_outgoing_file(*Client);
  252.                 break;
  253.             case DCC_FILEREAD:
  254.                 process_incoming_file(*Client);
  255.                 break;
  256.             case DCC_TALK:
  257.                 process_incoming_talk(*Client);
  258.                 break;
  259.             }
  260.         }
  261.         if ((*Client)->flags & DCC_DELETE)
  262.         {
  263.             dcc_add_deadclient(*Client);
  264.             Client = (&(**Client).next);
  265.         }
  266.         else
  267.             Client = (&(**Client).next);
  268.     }
  269.     message_from((char *) 0, LOG_CRAP);
  270.     (void) set_lastlog_msg_level(lastlog_level);
  271.     dcc_really_erase();
  272.     from_server = previous_server;
  273. }
  274.  
  275. /*
  276.  * Process a DCC command from the user.
  277.  */
  278. void
  279. process_dcc(args)
  280.     char    *args;
  281. {
  282.     char    *command;
  283.     int    i;
  284.     int    lastlog_level;
  285.  
  286.     if (!(command = next_arg(args, &args)))
  287.         return;
  288.     for (i = 0; dcc_commands[i].name != NULL; i++)
  289.     {
  290.         if (!my_stricmp(dcc_commands[i].name, command))
  291.         {
  292.             message_from((char *) 0, LOG_DCC);
  293.             lastlog_level = set_lastlog_msg_level(LOG_DCC);
  294.             dcc_commands[i].function(args);
  295.             message_from((char *) 0, LOG_CURRENT);
  296.             (void) set_lastlog_msg_level(lastlog_level);
  297.             return;
  298.         }
  299.     }
  300.     say("Unknown DCC command: %s", command);
  301. }
  302.  
  303. static    int
  304. dcc_open(Client)
  305.     DCC_list    *Client;
  306. {
  307.     char    *user,
  308.         *Type;
  309.     struct    sockaddr_in    localaddr,
  310.         remaddr;
  311.     struct    in_addr     myip;
  312.     int    sla,
  313.         rl = sizeof(remaddr);
  314.  
  315.     user = Client->user;
  316.     myip.s_addr = ntohl(MyHostAddr.s_addr);
  317.     Type = dcc_types[Client->flags & DCC_TYPES];
  318.     if (Client->flags & DCC_OFFER)
  319.     {
  320.         message_from((char *) 0, LOG_DCC);
  321.         if ((Client->write = connect_by_number(Client->remport,
  322.                   inet_ntoa(Client->remote))) < 0)
  323.         {
  324.             say("Unable to create connection: %s",
  325.                 errno ? strerror(errno) : "Unknown Host");
  326.             message_from((char *) 0, LOG_CURRENT);
  327.             dcc_erase(Client);
  328.             return 0;
  329.         }
  330.         Client->read = Client->write;
  331.         Client->flags &= ~DCC_OFFER;
  332.         Client->flags |= DCC_ACTIVE;
  333.         (void) getpeername(Client->read, (struct sockaddr *) &remaddr,
  334.             &rl);
  335.         if ((Client->flags & DCC_TYPES) != DCC_RAW)
  336.             say("DCC %s connection with %s[%s,%d] established",
  337.                 Type, user, inet_ntoa(remaddr.sin_addr),
  338.                 ntohs(remaddr.sin_port));
  339.         message_from((char *) 0, LOG_CURRENT);
  340.         Client->starttime = time(NULL);
  341.         Client->bytes_read = Client->bytes_sent = 0L;
  342.         return 1;
  343.     }
  344.     else
  345.     {
  346.         Client->flags |= DCC_WAIT;
  347.         message_from((char *) 0, LOG_DCC);
  348.         if ((Client->read = connect_by_number(0, empty_string)) < 0)
  349.         {
  350.             say("Unable to create connection: %s",
  351.                 errno ? strerror(errno) : "Unknown Host");
  352.             message_from((char *) 0, LOG_CURRENT);
  353.             dcc_erase(Client);
  354.             return 0;
  355.         }
  356.         sla = sizeof(struct sockaddr_in);
  357.         getsockname(Client->read, (struct sockaddr *) &localaddr, &sla);
  358.         if (Client->flags & DCC_TWOCLIENTS)
  359.         {
  360.             /* patch to NOT send pathname accross */
  361.             char    *nopath;
  362.  
  363.             if ((Client->flags & DCC_FILEOFFER) &&
  364.                 (nopath = rindex(Client->description, '/')))
  365.                 nopath++;
  366.             else
  367.                 nopath = Client->description;
  368.  
  369.             if (Client->filesize)
  370.                 send_ctcp(ctcp_type[in_ctcp_flag], user, "DCC",
  371.                      "%s %s %lu %u %ld", Type, nopath,
  372.                      (u_long) myip.s_addr,
  373.                      (u_short) ntohs(localaddr.sin_port),
  374.                      Client->filesize);
  375.             else
  376.                 send_ctcp(ctcp_type[in_ctcp_flag], user, "DCC",
  377.                      "%s %s %lu %u", Type, nopath,
  378.                      (u_long) myip.s_addr,
  379.                      (u_short) ntohs(localaddr.sin_port));
  380.             message_from((char *) 0, LOG_DCC);
  381.             say("Sent DCC %s request to %s", Type, user);
  382.             message_from((char *) 0, LOG_CURRENT);
  383.         }
  384.         /*
  385.          * Is this where dcc times are fucked up??  - phone
  386.          * Yes, it was..  and they are all hunky dory now..
  387.          */
  388.         Client->starttime = 0;
  389.         return 2;
  390.     }    
  391. }
  392.  
  393. void
  394. dcc_chat(args)
  395.     char    *args;
  396. {
  397.     char    *user;
  398.     DCC_list    *Client;
  399.  
  400.     if ((user = next_arg(args, &args)) == NULL)
  401.     {
  402.         say("You must supply a nickname for DCC CHAT");
  403.         return;
  404.     }
  405.     Client = dcc_searchlist("chat", user, DCC_CHAT, 1, (char *) 0);
  406.     if ((Client->flags&DCC_ACTIVE) || (Client->flags&DCC_WAIT))
  407.     {
  408.         say("A previous DCC CHAT to %s exists", user);
  409.         return;
  410.     }
  411.     Client->flags |= DCC_TWOCLIENTS;
  412.     dcc_open(Client);
  413. }
  414.  
  415. char    *
  416. dcc_raw_listen(port)
  417.     int    port;
  418. {
  419.     DCC_list    *Client;
  420.     char    PortName[10];
  421.     struct    sockaddr_in locaddr;
  422.     char    *RetName = NULL;
  423.     int    size;
  424.     int    lastlog_level;
  425.  
  426.     lastlog_level = set_lastlog_msg_level(LOG_DCC);
  427.     if (port && port < 1025)
  428.     {
  429.         say("Cannot bind to a privileged port");
  430.         (void) set_lastlog_msg_level(lastlog_level);
  431.         return NULL;
  432.     }
  433.     sprintf(PortName, "%d", port);
  434.     Client = dcc_searchlist("raw_listen", PortName, DCC_RAW_LISTEN, 1, (char *) 0);
  435.     if (Client->flags&DCC_WAIT)
  436.     {
  437.         say("A previous DCC RAW_LISTEN on %s exists", PortName);
  438.         (void) set_lastlog_msg_level(lastlog_level);
  439.         return RetName;
  440.     }
  441.     bzero((char *) &locaddr, sizeof(locaddr));
  442.     locaddr.sin_family = AF_INET;
  443.     locaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  444.     locaddr.sin_port = htons(port);
  445.     if (0 > (Client->read = socket(AF_INET, SOCK_STREAM, 0)))
  446.     {
  447.         dcc_erase(Client);
  448.         say("socket() failed: %s", strerror(errno));
  449.         (void) set_lastlog_msg_level(lastlog_level);
  450.         return RetName;
  451.     }
  452.     set_socket_options(Client->read);
  453.     if (bind(Client->read, (struct sockaddr *) &locaddr, sizeof(locaddr))
  454.                 == -1)
  455.     {
  456.         dcc_erase(Client);
  457.         say("Could not bind port: %s", strerror(errno));
  458.         (void) set_lastlog_msg_level(lastlog_level);
  459.         return RetName;
  460.     }
  461.     listen(Client->read, 4);
  462.     size = sizeof(locaddr);
  463.     Client->starttime = time((time_t *) 0);
  464.     getsockname(Client->read, (struct sockaddr *) &locaddr, &size);
  465.     Client->write = ntohs(locaddr.sin_port);
  466.     Client->flags |= DCC_ACTIVE;
  467.     sprintf(PortName, "%d", Client->write);
  468.     malloc_strcpy(&Client->user, PortName);
  469.     malloc_strcpy(&RetName, PortName);
  470.     (void) set_lastlog_msg_level(lastlog_level);
  471.     return RetName;
  472. }
  473.  
  474. char    *
  475. dcc_raw_connect(host, port)
  476.     char    *host;
  477.     u_short    port;
  478. {
  479.     DCC_list    *Client;
  480.     char    PortName[10];
  481.     struct    in_addr    address;
  482.     struct    hostent    *hp;
  483.     char    *RetName = (char *) 0;
  484.     int    lastlog_level;
  485.  
  486.     lastlog_level = set_lastlog_msg_level(LOG_DCC);
  487.     if ((address.s_addr = inet_addr(host)) == -1)
  488.     {
  489.         hp = gethostbyname(host);
  490.         if (!hp)
  491.         {
  492.             say("Unknown host: %s", host);
  493.             (void) set_lastlog_msg_level(lastlog_level);
  494.             return RetName;
  495.         }
  496.         bcopy(hp->h_addr, &address, sizeof(address));
  497.     }
  498.     sprintf(PortName, "%d", port);
  499.     Client = dcc_searchlist(host, PortName, DCC_RAW, 1, (char *) 0);
  500.     if (Client->flags & DCC_ACTIVE)
  501.     {
  502.         say("A previous DCC RAW to %s on %s exists", host, PortName);
  503.         (void) set_lastlog_msg_level(lastlog_level);
  504.         return RetName;
  505.     }
  506.     Client->remport = port;
  507.     bcopy((char *) &address, (char *) &Client->remote, sizeof(address));
  508.     Client->flags = DCC_OFFER | DCC_RAW;
  509.     if (!dcc_open(Client))
  510.         return RetName;
  511.     sprintf(PortName, "%d", Client->read);
  512.     malloc_strcpy(&Client->user, PortName);
  513.     if (do_hook(DCC_RAW_LIST, "%s %s E %d", PortName, host, port))
  514.         put_it("DCC RAW connection to %s on %s via %d established",
  515.                 host, PortName, port);
  516.     malloc_strcpy(&RetName, PortName);
  517.     (void) set_lastlog_msg_level(lastlog_level);
  518.     return RetName;
  519. }
  520.  
  521. char    *talk_errors[] =
  522. {
  523.     "<No Error>",
  524.     "User not logged in",
  525.     "Connection failed",
  526.     "Remote host does not recognise us",
  527.     "Your party is refusing writes",
  528.     "Unknown request",
  529.     "Unknown protocol version",
  530.     "Unable to decipher your address",
  531.     "Unable to decipher return address" /* How the hell does it get
  532.                         back then? */
  533. };
  534.  
  535. void
  536. dcc_talk(args)
  537.     char    *args;
  538. {
  539.     char    *user;
  540.     char    *host;
  541.     struct    hostent    *hp;
  542.     int    status;
  543.  
  544.     DCC_list    *Client;
  545.  
  546. #ifdef DAEMON_UID
  547.     if (getuid() == DAEMON_UID)
  548.     {
  549.          say("You are not permitted to use DCC TALK");
  550.         return;
  551.     }
  552. #endif /* DAEMON_UID */
  553.     if ((user = next_arg(args, &args)) == NULL)
  554.     {
  555.         say("You must supply a user[@host] for DCC TALK");
  556.         return;
  557.     }
  558.     if ((host = index(user, '@')) != NULL)
  559.         *(host++) = '\0';
  560.     else
  561.         host = MyHostName;
  562.     Client = dcc_searchlist(host, user, DCC_TALK, 1, (char *) 0);
  563.     if (Client->flags & DCC_ACTIVE || Client->flags & DCC_WAIT)
  564.     {
  565.         say("A previous DCC TALK to %s@%s exists", user, host);
  566.         return;
  567.     }
  568.     if (host != MyHostName)
  569.     {
  570.         if ((hp = gethostbyname(host)) == NULL)
  571.         {
  572.             say("Unable to find address for %s", host);
  573.             dcc_erase(Client);
  574.             return;
  575.         }
  576.         bcopy(hp->h_addr, (char *) &(Client->remote),
  577.             sizeof(struct in_addr));
  578.     }
  579.     else
  580.         bcopy((char *) &MyHostAddr, (char *) &(Client->remote),
  581.             sizeof(struct in_addr));
  582.     if ((Client->file = connect_by_number(-1, empty_string)) < 0)
  583.     {
  584.         say("Unable to create DCC TALK connection: %s",
  585.                 errno ? strerror(errno) : "Unknown Host");
  586.         dcc_erase(Client);
  587.         return;
  588.     }
  589.     say("Checking for invitation on caller's machine");
  590.     if (!(status = send_talk_control(Client, DCC_TALK_CHECK)))
  591.     {
  592.         close(Client->file);
  593.         dcc_erase(Client);
  594.         say("DCC TALK: connection timed out");
  595.         return;
  596.     }
  597.     if (--status || (Client->read = connect_by_number(Client->remport,
  598.                 inet_ntoa(Client->remote))) < 0)
  599.     {
  600.         say("Inviting %s@%s", Client->user, Client->description);
  601.         if ((Client->read = connect_by_number(0, empty_string)) == -1 ||
  602.             !send_talk_control(Client, DCC_TALK_INVITE) ||
  603.             !(status=send_talk_control(Client, DCC_TALK_ANNOUNCE)))
  604.         {
  605.             send_talk_control(Client, DCC_TALK_DELETE_LOCAL);
  606.             closesocket(Client->read);
  607.             close(Client->file);
  608.             dcc_erase(Client);
  609.             return;
  610.         }
  611.         if (--status)
  612.         {
  613.             closesocket(Client->read);
  614.             close(Client->file);
  615.             dcc_erase(Client);
  616.             say("DCC TALK: %s", talk_errors[status]);
  617.             return;
  618.         }
  619.         say("Waiting for your party to respond");
  620.         Client->flags |= DCC_WAIT;
  621.     }
  622.     else
  623.     {
  624.         say("Connected to %s@%s", Client->user, Client->description);
  625.         Client->write = Client->read;
  626.         send(Client->write,  "\008\025\027", 3, 0);
  627.         recv(Client->read, Client->talkchars, 3, 0);
  628.         Client->bytes_read = Client->bytes_sent = 3;
  629.         Client->flags |= DCC_ACTIVE;
  630.     }
  631. }
  632.  
  633. void
  634. dcc_summon(args)
  635.     char    *args;
  636. {
  637.     char    *user;
  638.     char    *host;
  639.     struct    hostent    *hp;
  640.     DCC_list *Client;
  641.  
  642.     if (0 == (user = next_arg(args, &args)))
  643.     {
  644.         say("You must supply a user[@host] for DCC SUMMON");
  645.         return;
  646.     }
  647.     if (0 != (host = index(user, '@')))
  648.         *host++ = '\0';
  649.     else
  650.         host = MyHostName;
  651.  
  652.     Client = dcc_searchlist(host, user, DCC_SUMMON, 1, (char *) 0);
  653.  
  654.     if (host != MyHostName)
  655.     {
  656.         if (0 == (hp = gethostbyname(host)))
  657.         {
  658.             say("Unable to find address for %s", host);
  659.             dcc_erase(Client);
  660.             return;
  661.         }
  662.         bcopy(hp->h_addr, (char *) &(Client->remote),
  663.             sizeof(struct in_addr));
  664.     }
  665.     else
  666.         bcopy((char *) &MyHostAddr, (char *) &(Client->remote),
  667.             sizeof(struct in_addr));
  668.     if ((Client->file = connect_by_number(-1, empty_string)) < 0)
  669.     {
  670.         say("Unable to create DCC SUMMON connection: %s",
  671.                 errno ? strerror(errno) : "Unknown Host");
  672.         return;
  673.     }
  674.     if (0 == send_talk_control(Client, DCC_TALK_SUMMON))
  675.         say("DCC SUMMON: connection timed out");
  676.     send_talk_control(Client, DCC_TALK_DELETE_SUMMON);
  677.     close(Client->file);
  678.     dcc_erase(Client);
  679. }
  680.  
  681. int    
  682. send_talk_control(Client, MessageType)
  683.     DCC_list    *Client;
  684.     int     MessageType;
  685. {
  686.     CTL_MSG    Message;
  687.     CTL_RESPONSE    Response;
  688.     static    long     SeqNum = 0;
  689.     struct    sockaddr_in SockAddr;
  690.     struct    timeval timeout;
  691.     fd_set    selset;
  692.     int    i;
  693.     int    dummy;
  694.  
  695.     Message.vers = TALK_VERSION;
  696.     Message.id_num = htonl(SeqNum);
  697.     SeqNum++; /* Not in the htonl because on some machines it's a macro */
  698.     dummy = sizeof(SockAddr);
  699.     getsockname(Client->file, (struct sockaddr *) &SockAddr, &dummy);
  700.     Message.ctl_addr = (*(struct sockaddr *) &SockAddr);
  701.     if (Client->read > 0)
  702.     {
  703.         getsockname(Client->read, (struct sockaddr *) &SockAddr,
  704.                 &dummy);
  705.         SockAddr.sin_addr=MyHostAddr;
  706.     }
  707.     Message.addr = (*(struct sockaddr *) &SockAddr);
  708.     strncpy(Message.l_name, username, NAME_SIZE);
  709.     Message.l_name[NAME_SIZE - 1] = '\0';
  710.     strncpy(Message.r_name, Client->user, NAME_SIZE);
  711.     Message.r_name[NAME_SIZE - 1] = '\0';
  712.     Message.r_tty[0] = '\0';
  713.     Message.pid = getpid();
  714.     SockAddr.sin_addr = Client->remote;
  715.     SockAddr.sin_port = htons(518);
  716.     switch(MessageType)
  717.     {
  718.     case DCC_TALK_CHECK:
  719.         Message.type = LOOK_UP;
  720.         break;
  721.     case DCC_TALK_INVITE:
  722.         Message.type = LEAVE_INVITE;
  723.         SockAddr.sin_addr = MyHostAddr;
  724.         break;
  725.     case DCC_TALK_ANNOUNCE:
  726.         Message.type = ANNOUNCE;
  727.         break;
  728.     case DCC_TALK_DELETE_LOCAL:
  729.         SockAddr.sin_addr = MyHostAddr;
  730.     case DCC_TALK_DELETE_REMOTE:
  731.         Message.type = DELETE;
  732.         break;
  733.     case DCC_TALK_SUMMON:
  734.         strcpy(Message.l_name, "I:");
  735.         strcat(Message.l_name, get_server_nickname(from_server));
  736.         Message.type = ANNOUNCE;
  737.         break;
  738.     case DCC_TALK_DELETE_SUMMON:
  739.         strcpy(Message.l_name, "I:");
  740.         strcat(Message.l_name, get_server_nickname(from_server));
  741.         Message.type = DELETE;
  742.         break;
  743.     }
  744.     for (i = 0; i < 3; i++)
  745.     {
  746.         if (sendto(Client->file, (char *) &Message, sizeof(Message), 0,
  747.                (struct sockaddr *) &SockAddr,
  748.                sizeof(SockAddr))!=sizeof(Message))
  749.         {
  750.             perror("sendto");
  751.             return 0;
  752.         }
  753.         timeout.tv_sec = 10;
  754.         timeout.tv_usec = 0;
  755.         FD_ZERO(&selset);
  756.         FD_SET(Client->file, &selset);
  757.         switch(select(Client->file+1, &selset, NULL, NULL, &timeout))
  758.         {
  759.         case -1:
  760.             perror("select");
  761.             return 0;
  762.         case 1:
  763.             do
  764.             {
  765.                 recv(Client->file, &Response,
  766.                     sizeof(Response), 0);
  767.                 FD_ZERO(&selset);
  768.                 FD_SET(Client->file, &selset);
  769.                 timeout.tv_sec = 0;
  770.                 timeout.tv_usec = 0;
  771.             }
  772.             while (select(Client->file + 1, &selset, NULL, NULL,
  773.                     &timeout) > 0);
  774.             if (Response.type != Message.type)
  775.                 continue;
  776.             if (LOOK_UP == Response.type &&
  777.                 SUCCESS == Response.answer)
  778.             {
  779.                 SockAddr = (*(struct sockaddr_in *)
  780.                     &Response.addr);
  781.                 Client->remote = SockAddr.sin_addr;
  782.                 Client->remport = ntohs(SockAddr.sin_port);
  783.             }
  784.             return Response.answer + 1;
  785.         }
  786.     }
  787.     return 0;
  788. }
  789.  
  790. void
  791. dcc_filesend(args)
  792.     char    *args;
  793. {
  794.     char    *user;
  795.     char    *filename,
  796.         *fullname;
  797.     DCC_list *Client;
  798.     define_big_buffer(FileBuf);
  799.     struct    stat    stat_buf;
  800.  
  801. #ifdef  DAEMON_UID
  802.     if (DAEMON_UID == getuid())
  803.     {
  804.         say("You are not permitted to use DCC to exchange files");
  805.         free_big_buffer(FileBuf);
  806.         return;
  807.     }
  808. #endif
  809.     if (0 == (user = next_arg(args, &args)) ||
  810.         0 == (filename = next_arg(args, &args)))
  811.     {
  812.         say("You must supply a nickname and filename for DCC SEND");
  813.         free_big_buffer(FileBuf);
  814.         return;
  815.     }
  816.     if (IS_FULL_PATH(filename))
  817.     {
  818.         strcpy(FileBuf, filename);
  819.     }
  820.     else if (*filename == '~')
  821.     {
  822.         if (0 == (fullname = expand_twiddle(filename)))
  823.         {
  824.             yell("Unable to expand %s", filename);
  825.             free_big_buffer(FileBuf);
  826.             return;
  827.         }
  828.         strcpy(FileBuf, fullname);
  829.         new_free(&fullname);
  830.     }
  831.     else
  832.     {
  833.         getcwd(FileBuf, BIG_BUFFER_SIZE);
  834.         strcat(FileBuf, "/");
  835.         strcat(FileBuf, filename);
  836.     }
  837.     if (0 != access(FileBuf, R_OK))
  838.     {
  839.         yell("Cannot access %s", FileBuf);
  840.         free_big_buffer(FileBuf);
  841.         return;
  842.     }
  843.     stat_file(FileBuf, &stat_buf);
  844.     if (stat_buf.st_mode & S_IFDIR)
  845.     {
  846.         yell("Cannot send a directory");
  847.         free_big_buffer(FileBuf);
  848.         return;
  849.     }
  850.     if (scanstr(FileBuf, "/etc/"))
  851.     {
  852.         yell("Send request rejected");
  853.         free_big_buffer(FileBuf);
  854.         return;
  855.     }
  856.     if (strlen(FileBuf) >= 7 &&
  857.         0 == strcmp(FileBuf + strlen(FileBuf) - 7, "/passwd"))
  858.     {
  859.         yell("Send request rejected");
  860.         free_big_buffer(FileBuf);
  861.         return;
  862.     }
  863.     filesize = stat_buf.st_size;
  864.     Client = dcc_searchlist(FileBuf, user, DCC_FILEOFFER, 1, filename);
  865.     filesize = 0;
  866.     if ((Client->flags & DCC_ACTIVE) || (Client->flags & DCC_WAIT))
  867.     {
  868.         say("A previous DCC SEND:%s to %s exists", FileBuf, user);
  869.         free_big_buffer(FileBuf);
  870.         return;
  871.     }
  872.     Client->flags |= DCC_TWOCLIENTS;
  873.     dcc_open(Client);
  874.     free_big_buffer(FileBuf);
  875. }
  876.  
  877.  
  878. void
  879. dcc_getfile(args)
  880.     char    *args;
  881. {
  882.     char    *user;
  883.     char    *filename;
  884.     DCC_list    *Client;
  885.     char    *fullname = (char *) 0;
  886.  
  887. #ifdef  DAEMON_UID
  888.     if (DAEMON_UID == getuid())
  889.     {
  890.         say("You are not permitted to use DCC to exchange files");
  891.         return;
  892.     }
  893. #endif
  894.     if (0 == (user = next_arg(args, &args)))
  895.     {
  896.         say("You must supply a nickname for DCC GET");
  897.         return;
  898.     }
  899.     filename = next_arg(args, &args);
  900.     if (0 == (Client = dcc_searchlist(filename, user, DCC_FILEREAD, 0, (char *) 0)))
  901.     {
  902.         if (filename)
  903.             say("No file (%s) offered in SEND mode by %s",
  904.                     filename, user);
  905.         else
  906.             say("No file offered in SEND mode by %s", user);
  907.         return;
  908.     }
  909.     if ((Client->flags & DCC_ACTIVE) || (Client->flags & DCC_WAIT))
  910.     {
  911.         say("A previous DCC GET:%s to %s exists", filename, user);
  912.         return;
  913.     }
  914.     if (0 == (Client->flags & DCC_OFFER))
  915.     {
  916.         say("I'm a teapot!");
  917.         dcc_erase(Client);
  918.         return;
  919.     }
  920.     Client->flags |= DCC_TWOCLIENTS;
  921.     Client->bytes_sent = Client->bytes_read = 0L;
  922.     if (!dcc_open(Client))
  923.         return;
  924.     if (0 == (fullname = expand_twiddle(Client->description)))
  925.         malloc_strcpy(fullname, Client->description);
  926.     if (-1 == (Client->file = open(fullname,
  927.                 O_WRONLY | O_BINARY | O_TRUNC | O_CREAT, 0644)))
  928.     {
  929.         say("Unable to open %s: %s", Client->description,
  930.                 errno ? strerror(errno) : "<No Error>");
  931.         closesocket(Client->read);
  932.         dcc_erase(Client);
  933.     }
  934.     new_free(&fullname);
  935. }
  936.  
  937.  
  938. void
  939. register_dcc_offer(user, type, description, address, port, size)
  940.     char    *user;
  941.     char    *type;
  942.     char    *description;
  943.     char    *address;
  944.     char    *port;
  945.     char    *size;
  946. {
  947.     DCC_list    *Client;
  948.     int    CType;
  949.     char    *c;
  950.     u_long    TempLong;
  951.     unsigned    TempInt;
  952.     int    do_auto = 0;    /* used in dcc chat collisions */
  953.  
  954.     if (0 != (c = rindex(description, '/')))
  955.         description = c + 1;
  956.     if ('.' == *description)
  957.         *description = '_';
  958.     if (size && *size)
  959.         filesize = atoi(size);
  960.     else
  961.         filesize = 0;
  962.     if (!my_stricmp(type, "CHAT"))
  963.         CType = DCC_CHAT;
  964. #ifndef  DAEMON_UID
  965.     else if (!strcmp(type, "SEND"))
  966. #else
  967.     else if (!strcmp(type, "SEND") && DAEMON_UID != getuid())
  968. #endif /*DAEMON_UID*/
  969.         CType = DCC_FILEREAD;
  970.     else
  971.         return;
  972.     Client = dcc_searchlist(description, user, CType, 1, (char *) 0);
  973.     filesize = 0;
  974.     if (Client->flags & DCC_WAIT)
  975.     {
  976.         closesocket(Client->read);
  977.         dcc_erase(Client);
  978.         if (DCC_CHAT == CType)
  979.         {
  980.             Client = dcc_searchlist(description, user, CType, 1, (char *) 0);
  981.             do_auto = 1;
  982.         }
  983.         else
  984.         {
  985.             say("DCC %s collision for %s:%s", type, user,
  986.                 description);
  987.             send_ctcp_reply(user, "DCC", "DCC %s collision occured while connecting to %s (%s)", type, nickname, description);
  988.             return;
  989.         }
  990.     }
  991.     if (Client->flags & DCC_ACTIVE)
  992.     {
  993.         say("Received DCC %s request from %s while previous session still active", type, user);
  994.         return;
  995.     }
  996.     Client->flags |= DCC_OFFER;
  997.     sscanf(address, "%lu", &TempLong);
  998.     Client->remote.s_addr = htonl(TempLong);
  999.     sscanf(port, "%u", &TempInt);
  1000.     Client->remport = TempInt;
  1001.     if (TempInt < 1024)
  1002.     {
  1003.         say("DCC %s (%s) request from %s rejected", type, description, user);
  1004.         dcc_erase(Client);
  1005.         return;
  1006.     }
  1007.     if ((u_long) 0 == TempLong || 0 == Client->remport)
  1008.     {
  1009.         dcc_erase(Client);
  1010.         return;
  1011.     }
  1012.     if (do_auto)
  1013.     {
  1014.         say("DCC CHAT already requested by %s, connecting...", user);
  1015.         dcc_chat(user);
  1016.     }
  1017.     else if (Client->filesize)
  1018.         say("DCC %s (%s %d) request received from %s", type, description, Client->filesize, user);
  1019.     else
  1020.         say("DCC %s (%s) request received from %s", type, description, user);
  1021.     return;
  1022. }
  1023.  
  1024. void
  1025. process_incoming_chat(Client)
  1026.     DCC_list    *Client;
  1027. {
  1028.     struct    sockaddr_in    remaddr;
  1029.     int    sra;
  1030.     define_big_buffer(tmp);
  1031.     long    bytesread;
  1032.     int    old_timeout;
  1033.  
  1034.     if (Client->flags & DCC_WAIT)
  1035.     {
  1036.         sra = sizeof(struct sockaddr_in);
  1037.         Client->write = accept(Client->read, (struct sockaddr *)
  1038.             &remaddr, &sra);
  1039. #if defined(ESIX) || defined(_Windows)
  1040.         mark_socket(Client->write);
  1041. #endif
  1042.         closesocket(Client->read);
  1043.         Client->read = Client->write;
  1044.         Client->flags &= ~DCC_WAIT;
  1045.         Client->flags |= DCC_ACTIVE;
  1046.         say("DCC chat connection to %s[%s,%d] established", Client->user,
  1047.             inet_ntoa(remaddr.sin_addr), ntohs(remaddr.sin_port));
  1048.         Client->starttime = time(NULL);
  1049.         free_big_buffer(tmp);
  1050.         return;
  1051.     }
  1052.     old_timeout = dgets_timeout(1);
  1053.     bytesread = dgets(tmp, BIG_BUFFER_SIZE, Client->read, (char *)0);
  1054.     (void) dgets_timeout(old_timeout);
  1055.     switch (bytesread)
  1056.     {
  1057.     case -1:
  1058.     case 0:
  1059.         say("DCC CHAT connection to %s lost", Client->user);
  1060.         closesocket(Client->read);
  1061.         Client->read = Client->write = -1;
  1062.         Client->flags |= DCC_DELETE;
  1063.         free_big_buffer(tmp);
  1064.         return;
  1065.     default:
  1066.         tmp[strlen(tmp) - 1]='\0';
  1067.         Client->bytes_read += bytesread;
  1068.         message_from(Client->user, LOG_DCC);
  1069.         if (do_hook(DCC_CHAT_LIST, "%s %s", Client->user, tmp))
  1070.         {
  1071.             if (away_set)
  1072.             {
  1073.                 time_t    t;
  1074.                 char    *msg = (char *) 0;
  1075.  
  1076.                 t = time(0);
  1077.                 msg = (char *) new_malloc(strlen(tmp) + 20);
  1078.                 sprintf(msg, "%s <%.16s>", tmp, ctime(&t));
  1079.                 strcpy(tmp, msg);
  1080.                 new_free(&msg);
  1081.             }
  1082.             put_it("=%s= %s", Client->user, tmp);
  1083.         }
  1084.         message_from((char *) 0, LOG_CURRENT);
  1085.         free_big_buffer(tmp);
  1086.         return;
  1087.     }
  1088. }
  1089.  
  1090. void
  1091. process_incoming_listen(Client)
  1092.     DCC_list    *Client;
  1093. {
  1094.     struct    sockaddr_in    remaddr;
  1095.     int    sra;
  1096.     char    FdName[10];
  1097.     DCC_list    *NewClient;
  1098.     int    new_socket;
  1099.     struct    hostent    *hp;
  1100. #if defined(__linux__) || defined(__sgi)
  1101.     const char    *Name;
  1102. #else
  1103.     char    *Name;
  1104. #endif
  1105.  
  1106.     sra = sizeof(struct sockaddr_in);
  1107.     new_socket = accept(Client->read, (struct sockaddr *) &remaddr,
  1108.                  &sra);
  1109.     if (0 != (hp = gethostbyaddr((char *)&remaddr.sin_addr,
  1110.         sizeof(remaddr.sin_addr), remaddr.sin_family)))
  1111.         Name = hp->h_name;
  1112.     else
  1113.         Name = inet_ntoa(remaddr.sin_addr);
  1114. #if defined(ESIX) || defined(_Windows)
  1115.     mark_socket(new_socket);
  1116. #endif
  1117.     sprintf(FdName, "%d", new_socket);
  1118.     NewClient = dcc_searchlist(Name, FdName, DCC_RAW, 1, (char *) 0);
  1119.     NewClient->starttime = time((time_t *) 0);
  1120.     NewClient->read = NewClient->write = new_socket;
  1121.     NewClient->remote = remaddr.sin_addr;
  1122.     NewClient->remport = remaddr.sin_port;
  1123.     NewClient->flags |= DCC_ACTIVE;
  1124.     NewClient->bytes_read = NewClient->bytes_sent = 0L;
  1125.     if (do_hook(DCC_RAW_LIST, "%s %s N %d", NewClient->user,
  1126.                         NewClient->description,
  1127.                         Client->write))
  1128.         say("DCC RAW connection to %s on %s via %d established",
  1129.                     NewClient->description,
  1130.                     NewClient->user,
  1131.                     Client->write);
  1132. }
  1133.  
  1134. void
  1135. process_incoming_raw(Client)
  1136.     DCC_list    *Client;
  1137. {
  1138.     define_big_buffer(tmp);
  1139.     long    bytesread;
  1140.     int     old_timeout;
  1141.  
  1142.     old_timeout = dgets_timeout(1);
  1143.     switch(bytesread = dgets(tmp, BIG_BUFFER_SIZE, Client->read, (char *)0))
  1144.     {
  1145.     case -1:
  1146.     case 0:
  1147.         if (do_hook(DCC_RAW_LIST, "%s %s C",
  1148.                 Client->user, Client->description))
  1149.             say("DCC RAW connection to %s on %s lost",
  1150.                 Client->user, Client->description);
  1151.         closesocket(Client->read);
  1152.         Client->read = Client->write = -1;
  1153.         Client->flags |= DCC_DELETE;
  1154.         (void) dgets_timeout(old_timeout);
  1155.         free_big_buffer(tmp);
  1156.         return;
  1157.     default:
  1158.         tmp[strlen(tmp) - 1] = '\0';
  1159.         Client->bytes_read += bytesread;
  1160.         if (do_hook(DCC_RAW_LIST, "%s %s D %s",
  1161.                 Client->user, Client->description, tmp))
  1162.             say("Raw data on %s from %s: %s",
  1163.                 Client->user, Client->description, tmp);
  1164.         (void) dgets_timeout(old_timeout);
  1165.         free_big_buffer(tmp);
  1166.         return;
  1167.     }
  1168. }
  1169.  
  1170. void
  1171. process_incoming_talk(Client)
  1172.     DCC_list    *Client;
  1173. {
  1174.     struct    sockaddr_in    remaddr;
  1175.     int    sra;
  1176.     define_big_buffer(tmp);
  1177.     long    bytesread;
  1178.     int     old_timeout;
  1179.  
  1180.     if (Client->flags & DCC_WAIT)
  1181.     {
  1182.         sra = sizeof(struct sockaddr_in);
  1183.         Client->write = accept(Client->read, (struct sockaddr *)
  1184.             &remaddr, &sra);
  1185. #if defined(ESIX) || defined(_Windows)
  1186.         mark_socket(Client->write);
  1187. #endif
  1188.         closesocket(Client->read);
  1189.         Client->read = Client->write;
  1190.         Client->flags &= ~DCC_WAIT;
  1191.         Client->flags |= DCC_ACTIVE;
  1192.         send_talk_control(Client, DCC_TALK_DELETE_LOCAL);
  1193.         close(Client->file);
  1194.         send(Client->write, "\010\025\027", 3, 0);
  1195.         recv(Client->read, Client->talkchars, 3, 0);
  1196.         Client->bytes_read = Client->bytes_sent = 3;
  1197.         say("TALK connection to %s[%s,%d] established", Client->user,
  1198.             inet_ntoa(remaddr.sin_addr), ntohs(remaddr.sin_port));
  1199.         free_big_buffer(tmp);
  1200.         return;
  1201.     }
  1202.     old_timeout = dgets_timeout(1);
  1203.     switch(bytesread = dgets(tmp, -BIG_BUFFER_SIZE, Client->read,
  1204.             Client->talkchars))
  1205.     {
  1206.     case -2: return;
  1207.     case -1:
  1208.     case 0:
  1209.         say("TALK connection to %s lost", Client->user);
  1210.         closesocket(Client->read);
  1211.         Client->read=Client->write = -1;
  1212.         Client->flags |= DCC_DELETE;
  1213.         (void) dgets_timeout(old_timeout);
  1214.         free_big_buffer(tmp);
  1215.         return;
  1216.     default:
  1217.         Client->bytes_read += bytesread;
  1218.         message_from(Client->user, LOG_DCC);
  1219.         if (do_hook(TALK_LIST, "%s %s", Client->user, tmp))
  1220.             put_it("+%s+ %s", Client->user, tmp);
  1221.         message_from((char *) 0, LOG_CURRENT);
  1222.         (void) dgets_timeout(old_timeout);
  1223.         free_big_buffer(tmp);
  1224.         return;
  1225.     }
  1226. }
  1227.  
  1228. void
  1229. process_outgoing_file(Client)
  1230.     DCC_list    *Client;
  1231. {
  1232.     struct    sockaddr_in    remaddr;
  1233.     int    sra;
  1234.     define_big_buffer(tmp);
  1235.     u_32int_t    bytesrecvd;
  1236.     int    bytesread;
  1237.     int    BlockSize;
  1238.     int    recv_error;
  1239.  
  1240.     if (Client->flags & DCC_WAIT)
  1241.     {
  1242.         sra = sizeof(struct sockaddr_in);
  1243.         Client->write = accept(Client->read,
  1244.                 (struct sockaddr *) &remaddr, &sra);
  1245. #if defined(ESIX) || defined(_Windows)
  1246.         mark_socket(Client->write);
  1247. #endif
  1248.         closesocket(Client->read);
  1249.         Client->read = Client->write;
  1250.         Client->flags &= ~DCC_WAIT;
  1251.         Client->flags |= DCC_ACTIVE;
  1252.         Client->bytes_sent = 0L;
  1253.         Client->starttime = time(NULL);
  1254.         say("DCC SEND connection to %s[%s,%d] established", Client->user,
  1255.             inet_ntoa(remaddr.sin_addr), ntohs(remaddr.sin_port));
  1256.         if ((Client->file = open(Client->description, O_RDONLY | O_BINARY)) == -1)
  1257.         {
  1258.             say("Unable to open %s: %s\n", Client->description,
  1259.                 errno ? strerror(errno) : "Unknown Host");
  1260.             closesocket(Client->read);
  1261.             Client->read = Client->write = (-1);
  1262.             Client->flags |= DCC_DELETE;
  1263.             free_big_buffer(tmp);
  1264.             return;
  1265.         }
  1266.     }
  1267.     else 
  1268.     { 
  1269.         if ((bytesread = recv(Client->read, &bytesrecvd, sizeof(u_32int_t), 0))
  1270.             < sizeof(u_32int_t))
  1271.         {
  1272. #ifdef _Windows
  1273.             recv_error = WSAGetLastError();
  1274.             if (bytesread == -1 &&
  1275.                 recv_error == WSAEWOULDBLOCK ||
  1276.                 recv_error == WSAEINTR)
  1277.                 return;
  1278. #endif
  1279.               
  1280.                    say("DCC SEND:%s connection to %s lost",
  1281.                 Client->description, Client->user);
  1282.             closesocket(Client->read);
  1283.             Client->read = Client->write = (-1);
  1284.             Client->flags |= DCC_DELETE;
  1285.             close(Client->file);
  1286.             free_big_buffer(tmp);
  1287.             return;
  1288.         }
  1289.         else
  1290.             if (ntohl(bytesrecvd) != Client->bytes_sent)
  1291.             {
  1292.                 free_big_buffer(tmp);
  1293.                 return;
  1294.             }
  1295.     }
  1296.     BlockSize = get_int_var(DCC_BLOCK_SIZE_VAR);
  1297.     if (BlockSize > BIG_BUFFER_SIZE)
  1298.         BlockSize = BIG_BUFFER_SIZE;
  1299.     else if (BlockSize < 16)
  1300.         BlockSize = 16;
  1301.     if ((bytesread = read(Client->file, tmp, BIG_BUFFER_SIZE)) != 0)
  1302.     {
  1303.         send(Client->write, tmp, bytesread, 0);
  1304.         Client->bytes_sent += bytesread;
  1305.     }
  1306.     else
  1307.     {
  1308.         /*
  1309.          * We do this here because lame Ultrix doesn't let us
  1310.          * call put_it() with a float.  Perhaps put_it() should
  1311.          * be fixed properly, and this kludge removed ..
  1312.          * sometime....  -phone jan, 1993.
  1313.          */
  1314.  
  1315.         char    lame_ultrix[10];    /* should be plenty */
  1316.         time_t    xtime = time(NULL) - Client->starttime;
  1317.         double    sent = (double)Client->bytes_sent;
  1318.  
  1319.         if (sent <= 0)
  1320.             sent = 1;
  1321.         sent /= (double)1024.0;
  1322.         if (xtime <= 0)
  1323.             xtime = 1;
  1324.         sprintf(lame_ultrix, "%2.4g", (sent / (double)xtime));
  1325.         say("DCC SEND:%s to %s completed %s kb/sec",
  1326.             Client->description, Client->user, lame_ultrix);
  1327.         closesocket(Client->read);
  1328.         Client->read = Client->write = -1;
  1329.         Client->flags |= DCC_DELETE;
  1330.         close(Client->file);
  1331.         free_big_buffer(tmp);
  1332.         return;
  1333.     }
  1334.     free_big_buffer(tmp);
  1335.  
  1336. }
  1337.  
  1338. void
  1339. process_incoming_file(Client)
  1340.     DCC_list    *Client;
  1341. {
  1342.     define_big_buffer(tmp);
  1343.     u_32int_t    bytestemp;
  1344.     int    bytesread;
  1345.     int    recv_error;
  1346.  
  1347.     if ((bytesread = recv(Client->read, tmp, BIG_BUFFER_SIZE, 0)) <= 0)
  1348.     {
  1349.         /*
  1350.          * We do this here because lame Ultrix doesn't let us
  1351.          * call put_it() with a float.  Perhaps put_it() should
  1352.          * be fixed properly, and this kludge removed ..
  1353.          * sometime....  -phone jan, 1993.
  1354.          */
  1355.  
  1356.         char    lame_ultrix[10];        /* should be plenty */
  1357.         time_t    xtime = time(NULL) - Client->starttime;
  1358.         double    sent = (double)Client->bytes_read;
  1359.  
  1360. #ifdef _Windows
  1361.         recv_error = WSAGetLastError();
  1362.         if (bytesread == -1 &&
  1363.             recv_error == WSAEWOULDBLOCK ||
  1364.             recv_error == WSAEINTR)
  1365.             return;
  1366. #endif
  1367.         if (sent <= 0)
  1368.             sent = 1;
  1369.         sent /= (double)1024.0;
  1370.         if (xtime <= 0)
  1371.             xtime = 1;
  1372.         sprintf(lame_ultrix, "%2.4g", (sent / (double)xtime));
  1373.         say("DCC GET:%s from %s completed %s kb/sec",
  1374.             Client->description, Client->user, lame_ultrix);
  1375.         closesocket(Client->read);
  1376.         close(Client->file);
  1377.         Client->read = Client->write = (-1);
  1378.         Client->flags |= DCC_DELETE;
  1379.         free_big_buffer(tmp);
  1380.         return;
  1381.     }
  1382.     write(Client->file, tmp, bytesread);
  1383.     Client->bytes_read += bytesread;
  1384.     bytestemp = htonl(Client->bytes_read);
  1385.     send(Client->write, &bytestemp, sizeof(u_32int_t), 0);
  1386.     free_big_buffer(tmp);
  1387. }
  1388.  
  1389. /* flag == 1 means show it.  flag == 0 used by redirect */
  1390.  
  1391. void
  1392. dcc_message_transmit(user, text, type, flag)
  1393.     char    *user;
  1394.     char    *text;
  1395.     int    type,
  1396.         flag;
  1397. {
  1398.     DCC_list    *Client;
  1399.     define_big_buffer(tmp);
  1400.     int    lastlog_level;
  1401.     char    thing = '\0';
  1402.     int    list = 0;
  1403.     char    *host = (char *) 0;
  1404.  
  1405.     switch(type)
  1406.     {
  1407.     case DCC_TALK:
  1408.         if ((host = index(user, '@')) != NULL)
  1409.             *(host++) = '\0';
  1410.         thing = '+';
  1411.         list = SEND_TALK_LIST;
  1412.         break;
  1413.     case DCC_CHAT:
  1414.         host = "chat";
  1415.         thing = '=';
  1416.         list = SEND_DCC_CHAT_LIST;
  1417.         break;
  1418.     case DCC_RAW:
  1419.         host = next_arg(text, &text);
  1420.         if (!host)
  1421.         {
  1422.             say("No host specified for DCC RAW");
  1423.             return;
  1424.         }
  1425.         break;
  1426.     }
  1427.     if (!(Client = dcc_searchlist(host, user, type, 0, (char *) 0)) ||
  1428.             !(Client->flags&DCC_ACTIVE))
  1429.     {
  1430.         say("No active DCC %s:%s connection for %s",
  1431.             dcc_types[type], host?host:"<any>", user);
  1432.         free_big_buffer(tmp);
  1433.         return;
  1434.     }
  1435.     lastlog_level = set_lastlog_msg_level(LOG_DCC);
  1436.     message_from(Client->user, LOG_DCC);
  1437.     strmcpy(tmp, text, BIG_BUFFER_SIZE);
  1438.     strmcat(tmp, "\n", BIG_BUFFER_SIZE); 
  1439.     send(Client->write, tmp, strlen(tmp), 0);
  1440.     Client->bytes_sent += strlen(tmp);
  1441.     if (flag)
  1442.     {
  1443.         if (type != DCC_RAW)
  1444.             if (do_hook(list, "%s %s", Client->user, text))
  1445.                 put_it("=> %c%s%c %s", thing, Client->user,
  1446.                             thing, text);
  1447.     }
  1448.     set_lastlog_msg_level(lastlog_level);
  1449.     message_from((char *) 0, LOG_CURRENT);
  1450.         free_big_buffer(tmp);
  1451.     return;
  1452. }
  1453.  
  1454. void
  1455. dcc_chat_transmit(user,    text)
  1456.     char    *user;
  1457.     char    *text;
  1458. {
  1459.     dcc_message_transmit(user, text, DCC_CHAT, 1);
  1460. }
  1461.  
  1462. void
  1463. dcc_tmsg(args)
  1464.     char    *args;
  1465. {
  1466.     char    *user;
  1467.  
  1468.     if (!(user = next_arg(args, &args)))
  1469.     {
  1470.         say("You must specify a connection for a DCC TMSG");
  1471.         return;
  1472.     }
  1473.     dcc_message_transmit(user, args, DCC_TALK, 1);
  1474. }
  1475.  
  1476. void
  1477. dcc_send_raw(args)
  1478.     char    *args;
  1479. {
  1480.     char    *name;
  1481.  
  1482.     if (!(name = next_arg(args, &args)))
  1483.     {
  1484.         say("No name specified for DCC RAW");
  1485.         return;
  1486.     }
  1487.     dcc_message_transmit(name, args, DCC_RAW, 1);
  1488. }
  1489.  
  1490. /*
  1491.  * dcc_time: Given a time value, it returns a string that is in the
  1492.  * format of "hours:minutes:seconds month day year" .  Used by 
  1493.  * dcc_list() to show the start time.
  1494.  */
  1495. static    char    *
  1496. dcc_time(time)
  1497.     time_t    time;
  1498. {
  1499.     struct    tm    *btime;
  1500.     char    *buf;
  1501.     static    char    *months[] = 
  1502.     {
  1503.         "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  1504.         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  1505.     };
  1506.  
  1507.     btime = localtime(&time);
  1508.     buf = (char *) malloc(22);
  1509.     if (sprintf(buf, "%-2.2d:%-2.2d:%-2.2d %s %-2.2d %d", btime->tm_hour,
  1510.             btime->tm_min, btime->tm_sec, months[btime->tm_mon],
  1511.             btime->tm_mday, btime->tm_year + 1900))
  1512.         return buf;
  1513.     else
  1514.         return empty_string;
  1515. }
  1516.  
  1517. void
  1518. dcc_list(args)
  1519.     char    *args;
  1520. {
  1521.     DCC_list    *Client;
  1522.     static    char    *format =
  1523.             "%-7.7s %-9.9s %-9.9s %-20.20s %-8.8s %-8.8s %s";
  1524.     unsigned    flags;
  1525.  
  1526.     put_it(format, "Type", "Nick", "Status", "Start time", "Sent", "Read",
  1527.             "Arguments");
  1528.     for (Client = ClientList ; Client != NULL ; Client = Client->next)
  1529.     {
  1530.         char    sent[9],
  1531.             read[9];
  1532.         char    *time;
  1533.  
  1534.         sprintf(sent, "%ld", (long) Client->bytes_sent);
  1535.         sprintf(read, "%ld", (long) Client->bytes_read);
  1536.         time = (Client->starttime) ? dcc_time(Client->starttime) : "",
  1537.         flags = Client->flags;
  1538.         put_it(format, dcc_types[flags&DCC_TYPES],
  1539.                 Client->user,
  1540.                 flags&DCC_DELETE ? "Closed" :
  1541.                 flags&DCC_ACTIVE ? "Active" :
  1542.                 flags&DCC_WAIT ? "Waiting" :
  1543.                 flags&DCC_OFFER ? "Offered" : "Unknown",
  1544.                 time, sent, read, Client->description);
  1545.         if (*time)
  1546.             new_free(&time);
  1547.     }
  1548. }
  1549.  
  1550. void
  1551. dcc_close(args)
  1552.     char    *args;
  1553. {
  1554.     DCC_list    *Client;
  1555.     unsigned    flags;
  1556.     char    *Type;
  1557.     char    *user;
  1558.     char    *description;
  1559.     int    CType;
  1560.  
  1561.     if (!(Type = next_arg(args, &args)) || !(user=next_arg(args, &args)))
  1562.     {
  1563.         say("you must specify a type and nick for DCC CLOSE");
  1564.         return;
  1565.     }
  1566.     description = next_arg(args, &args);
  1567.     for (CType = 0; dcc_types[CType] != NULL; CType++)
  1568.         if (!my_stricmp(Type, dcc_types[CType]))
  1569.             break;
  1570.     if (!dcc_types[CType])
  1571.     {
  1572.         say("Unknown DCC type: %s", Type);
  1573.         return;
  1574.     }
  1575.     if (Client = dcc_searchlist(description, user, CType, 0, description))
  1576.     {
  1577.         flags = Client->flags;
  1578.         if (flags & DCC_DELETE)
  1579.             return;
  1580.         if ((flags & DCC_WAIT) || (flags & DCC_ACTIVE))
  1581.         {
  1582.             closesocket(Client->read);
  1583.             if (Client->file)
  1584.                 close(Client->file);
  1585.         }
  1586.         say("DCC %s:%s to %s closed", Type,
  1587.             description ? description : "<any>", user);
  1588.         dcc_erase(Client);
  1589.     }
  1590.     else
  1591.         say("No DCC %s:%s to %s found", Type,
  1592.             description ? description : "<any>", user);
  1593. }
  1594.  
  1595. void
  1596. dcc_rename(args)
  1597.     char    *args;
  1598. {
  1599.     DCC_list    *Client;
  1600.     char    *user;
  1601.     char    *description;
  1602.     char    *newdesc;
  1603.     char    *temp;
  1604.     
  1605.     if (!(user = next_arg(args, &args)) || !(temp = next_arg(args, &args)))
  1606.     {
  1607.         say("you must specify a nick and new filename for DCC RENAME");
  1608.         return;
  1609.     }
  1610.     if ((newdesc = next_arg(args, &args)) != NULL)
  1611.         description = temp;
  1612.     else
  1613.     {
  1614.         newdesc = temp;
  1615.         description = NULL;
  1616.     }
  1617.     if ((Client = dcc_searchlist(description, user, DCC_FILEREAD, 0, (char *) 0)))
  1618.     {
  1619.         if (!(Client->flags & DCC_OFFER))
  1620.         {
  1621.             say("Too late to rename that file");
  1622.             return;
  1623.         }
  1624.         new_free(&(Client->description));
  1625.         malloc_strcpy(&(Client->description), newdesc);
  1626.         say("File %s from %s renamed to %s",
  1627.              description ? description : "<any>", user, newdesc);
  1628.     }
  1629.     else
  1630.         say("No file %s from %s found",
  1631.             description ? description : "<any>", user);
  1632. }
  1633.  
  1634. /*
  1635.  * close_all_dcc:  We call this when we create a new process so that
  1636.  * we don't leave any fd's lying around, that won't close when we
  1637.  * want them to..
  1638.  */
  1639.  
  1640. void
  1641. close_all_dcc()
  1642. {
  1643.     DCC_list *Client;
  1644.  
  1645.     for (;(Client = ClientList);)
  1646.         dcc_erase(Client);
  1647. }
  1648.